package com.msgc.utils.crypto.hash;

import com.msgc.utils.crypto.common.ByteSpecification;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;

/**
 * Secure Hash Algorithm
 * 即使对同一个字符串hash，hash的结果也几乎完全不一致
 * @author liuyanming 2019年10月27日
 */
public class Sha256Utils implements ByteSpecification {

	/**
	 * 获取摘要
	 */
	public static byte[] hash(byte[] toHashBytes) {
		if(toHashBytes == null || toHashBytes.length == 0){
			throw new IllegalArgumentException("text can't be empty!");
		}
		try {
			MessageDigest digest = MessageDigest.getInstance("SHA-256");
			digest.update(toHashBytes);
			return digest.digest();
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
			throw new RuntimeException("NoSuchAlgorithmException SHA-256", e);
		}
	}

	public static String hash(String toHashStr) {
		return ByteSpecification.encodeToString(hash(toHashStr.getBytes(CHARSET_UTF_8)));
	}

	/**
	 *	验证原文hash后是否与密文相同
	 * @param text		cipher的明文
	 * @param digestBytes	text hash厚的
	 */
	public static boolean verifyHash(byte[] text, byte[] digestBytes){
		return Arrays.equals(hash(text), digestBytes);
	}

	/**
	 *	验证原文hash后是否与密文相同
	 * @param text		cipher的明文
	 * @param cipher	text hash厚的
	 */
	public static boolean verifyHash(String text, String cipher){
		return verifyHash(text.getBytes(CHARSET_UTF_8), ByteSpecification.decodeToBytes(cipher));
	}

	public static void main(String[] args) {

		System.out.println("========== 测试多次调用，得到的hash值是否不同 ==========");
		for (int i = 0; i < 30; i++) {
			System.out.println("hashValue —— "+ Sha256Utils.hash("123"));
		}

		System.out.println("========== 测试byte进行hash后验证 ==========");
		byte[] textBytes = "123".getBytes(CHARSET_UTF_8);
		byte[] cipherBytes = Sha256Utils.hash(textBytes);
		System.out.println("是否成功：" + Sha256Utils.verifyHash(textBytes, cipherBytes));

		System.out.println("========== 测试字符串进行hash后验证 ==========");
		String text = "123";
		String cipher = Sha256Utils.hash(text);
		System.out.println("是否成功：" + Sha256Utils.verifyHash(text, cipher));

	}


}
